import React, { useEffect } from 'react';

/* counter 自己的 state 和 reducer 写在一起*/
let initState = {
    count: 0
};
function counterReducer(state, action) {
/* 注意：如果 state 没有初始值，那就给他初始值！！*/  
    if (!state) {
        state = initState;
    }
    switch (action.type) {
        case 'INCREMENT':
            return {
                count: state.count + 1
            };
        default:    
            return state;
    }
}

function InfoReducer(state, action) {
    switch (action.type) {
        case 'SET_NAME':
            return {
                ...state,
                name: action.name
            };
        case 'SET_DESCRIPTION':
            return {
                ...state,
                description: action.description
            };
        default:
            return state;
    }
}

function combineReducers(reducers) {
    /* reducerKeys = ['counter', 'info']*/
    const reducerKeys = Object.keys(reducers);
  
    /* 返回合并后的新的reducer函数*/
    return function combination(state = {}, action) {
        /* 生成的新的state*/
        const nextState = {};
  
        /* 遍历执行所有的reducers，整合成为一个新的state*/
        for (let i = 0; i < reducerKeys.length; i++) {
            const key = reducerKeys[i];
            const reducer = reducers[key];
            /* 之前的 key 的 state*/
            const previousStateForKey = state[key];
            /* 执行 分 reducer，获得新的state*/
            const nextStateForKey = reducer(previousStateForKey, action);
  
            nextState[key] = nextStateForKey;
        }
        // console.log(nextState);
        return nextState;
    };
}

const createStore = function(reducer, initState, rewriteCreateStoreFunc) {
    if (rewriteCreateStoreFunc) {
        const newCreateStore = rewriteCreateStoreFunc(createStore);
        return newCreateStore(reducer, initState);
    }
    
    let state = initState;
    let listeners = [];
  
    /* 订阅*/
    function subscribe(listener) {
        listeners.push(listener);
    }
  
    function dispatch(action) {
        /* 请按照我的计划修改 state*/  
        state = reducer(state, action);
        /* 通知*/
        for (let i = 0; i < listeners.length; i++) {
            const listener = listeners[i];
            listener();
        }
    }
  
    function getState() {
        return state;
    }

    /* 注意！！！只修改了这里，用一个不匹配任何计划的 type，来获取初始值 */
    dispatch({ type: Symbol() });
    return {
        subscribe,
        dispatch,
        getState
    };
};

export default function Redux2() {

    const reducer = combineReducers({
        counter: counterReducer
    });
    /* 把plan函数*/
    // const store = createStore(reducer);
    // const next  = store.dispatch;
    
    const applyMiddleware = function(...middlewares) {
        /* 返回一个重写createStore的方法*/
        return function rewriteCreateStoreFunc(oldCreateStore) {
            /* 返回重写后新的 createStore*/
            return function newCreateStore(reducer, initState) {
            /* 1. 生成store*/
                const store = oldCreateStore(reducer, initState);
                /* 给每个 middleware 传下store，相当于 const logger = loggerMiddleware(store);*/
                /* const chain = [exception, time, logger]*/
                const chain = middlewares.map(middleware => middleware(store));
                let dispatch = store.dispatch;

                /* 实现 exception(time((logger(dispatch))))*/
                chain.reverse().map(middleware => {
                    dispatch = middleware(dispatch);
                });
                /* 2. 重写 dispatch*/
                store.dispatch = dispatch;
                return store;
            };
        };
    };

    const loggerMiddleware = (store) => (next) => (action) => {
        console.log('this state', store.getState());
        console.log('action', action);
        next(action);
        console.log('next state', store.getState());
    };

    const exceptionMiddleware = (store) => (next) => (action) => {
        try {
            console.log('第一个midddelware');
            next(action);
        } catch (err) {
            console.error('错误报告: ', err);
        }
    };

    const timeMiddleware = (store) => (next) => (action) => {
        console.log('time', new Date().getTime());
        next(action);
    };

    const rewriteCreateStoreFunc = applyMiddleware(exceptionMiddleware, timeMiddleware, loggerMiddleware);
    const store = createStore(reducer, {}, rewriteCreateStoreFunc);

    // store.dispatch = exception(time(logger(next)));
    store.subscribe(() => {
        let state = store.getState();
        console.log(state.counter.count);
    });

    useEffect(() => {
        store.dispatch({
            type: 'INCREMENT'
        });
        /* 自增*/
        // store.dispatch({
        //     type: 'INCREMENT'
        // });
      
        /* 修改 name*/
        // store.dispatch({
        //     type: 'SET_NAME',
        //     name: '前端九部2号'
        // });
    }, []);
    return (
        <div>
           手写redux
        </div>
    );
}